package cn.tworice.auth.interceptor;


import cn.tworice.auth.config.AuthProperties;
import cn.tworice.auth.constant.ConfigConst;
import cn.tworice.auth.service.VerifyManger;
import cn.tworice.auth.util.TokenUtils;
import cn.tworice.common.util.RequestUtil;
import cn.tworice.common.util.StringUtils;
import cn.tworice.common.vo.RequestResult;
import cn.tworice.common.vo.StateCodeConst;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * 管理系统身份验证拦截器
 */
public class AuthInterceptor implements HandlerInterceptor {

    @Autowired
    private VerifyManger verifyManger;

    @Resource
    private AuthProperties authProperties;

    @Value("${tworice.login.tokenTimeout:86400000}")
    private long tokenTimeout;

    @Value("${tworice.dev:false}")
    private boolean dev;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
        if(dev || request.getRequestURI().endsWith("template")){
            return true;
        }

        String origin  = request.getHeader(HttpHeaders.ORIGIN);
        if (origin != null) {
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, HEAD");
            response.setHeader("Access-Control-Allow-Headers", "Content-Type, Token, adminID");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Expose-Headers", "New-Token");
        }
        try {
            String token = request.getHeader(ConfigConst.ACCEPT_TOKEN);
            String adminID = request.getHeader(ConfigConst.ADMIN_ID);
            String url = request.getRequestURI();
            if (StringUtils.isEmpty(token) || !verifyManger.auth(adminID,token,url)) {
                RequestUtil.returnJson(response, RequestResult.error(StateCodeConst.LOGIN_ERROR,"请进行登录"));
                return false;
            }
            // 解码
            DecodedJWT decode = JWT.decode(token);
            // 验证密钥是否正确
            Algorithm algorithm = Algorithm.HMAC256(adminID);
            algorithm.verify(decode);
            // 有效期是否超时
            Date expiresAt = decode.getExpiresAt();
            if (expiresAt.getTime() < System.currentTimeMillis()) {
                RequestUtil.returnJson(response, RequestResult.error(StateCodeConst.LOGIN_ERROR, "Token未授权或已超时"));
                return false;
            } else if (expiresAt.getTime() < System.currentTimeMillis() + authProperties.getRefreshTime()) {
                // 刷新Token
                String newToken = TokenUtils.getAdminToken(adminID, tokenTimeout);
                response.setHeader("New-Token", newToken);
                verifyManger.refresh(adminID, newToken);
            }
            return true;
        }catch (JWTDecodeException ex){
            RequestUtil.returnJson(response, RequestResult.error(StateCodeConst.LOGIN_ERROR,"Token格式不合法"));
        }catch (Exception ex){
            throw new RuntimeException(ex);
        }
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
